package com.linb.pan.server.common.aspect;

import com.linb.pan.core.response.R;
import com.linb.pan.core.response.ResponseCode;
import com.linb.pan.core.utils.JwtUtil;
import com.linb.pan.server.common.utils.ShareIdUtil;
import com.linb.pan.server.modules.share.constants.ShareConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

@Component
@Aspect
@Slf4j
public class ShareCodeAspect {

    //参数中获取
    private static final String SHARE_CODE_AUTH_PARAM_NAME = "shareToken";

    //请求头中获取
    private static final String SHARE_CODE_AUTH_HEADER_NAME = "Share-Token";

    //切点表达式
    private static final String POINT_CUT = "@annotation (com.linb.pan.server.common.annotation.NeedShareCode)";

    /**
     * 切点模板方法
     */
    @Pointcut(value = POINT_CUT)
    public void shareAuth() {
    }

    /**
     * 环绕增强
     */
    @Around("shareAuth()")
    public Object shareAuthAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //获取请求路径
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        //获取URI
        String requestURI = request.getRequestURI();
        log.info("[分享码拦截请求]获取URI: {}", requestURI);
        //校验token有效性
        boolean isValidToken = checkShareId(request);
        if (!isValidToken) {
            log.warn("[分享码拦截请求]无效token，uri为: {}", requestURI);
            return R.fail(ResponseCode.ACCESS_DENIED);
        }
        log.info("[分享码拦截请求]校验通过，uri为:{} ", requestURI);
        return proceedingJoinPoint.proceed();
    }

    /**
     * 校验token有效性
     */
    private boolean checkShareId(HttpServletRequest request) {
        //从请求头中获取
        String accessToken = request.getHeader(SHARE_CODE_AUTH_HEADER_NAME);
        if (StringUtils.isBlank(accessToken)) {
            accessToken = request.getParameter(SHARE_CODE_AUTH_PARAM_NAME);
        }
        if (StringUtils.isBlank(accessToken)) {
            return false;
        }
        //校验token
        Object shareId = JwtUtil.analyzeToken(accessToken, ShareConstants.SHARE_ID);
        if (Objects.isNull(shareId)) {
            return false;
        }
        //保存到ThreadLocal
        saveShareId(Long.valueOf(String.valueOf(shareId)));
        return true;
    }

    /**
     * 将shareId保存到ThreadLocal
     */
    private void saveShareId(Long shareId) {
        ShareIdUtil.set(shareId);
    }

}
